﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;

namespace Qreed.Windows
{
    internal class TextScope : IComparable<TextScope>
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="TextScope"/> class.
        /// </summary>
        /// <param name="parent">The parent.</param>
        /// <param name="isScope">if set to <c>true</c> [is scope].</param>
        /// <param name="offset">The offset.</param>
        /// <param name="length">The length.</param>
        /// <param name="text">The text.</param>
        /// <param name="displayText">The display text.</param>
        public TextScope(ScopeTextBox parent, bool isScope, int offset, int length, string text, string name)
        {
            _parent = parent;
            _isScope = isScope;
            _offset = offset;
            _length = length;
            _text = text;
            _name = name;
        }

        private ScopeTextBox _parent;
        /// <summary>
        /// Gets or sets the parent.
        /// </summary>
        /// <value>The parent.</value>
        public ScopeTextBox Parent
        {
            get { return this._parent; }
            set { this._parent = value; }
        }			

        private bool _isScope;
        /// <summary>
        /// Gets or sets a value indicating whether this instance is a scope.
        /// </summary>
        /// <value><c>true</c> if this instance is a scope; otherwise, <c>false</c>.</value>
        public bool IsScope
        {
            get { return this._isScope; }
            set { this._isScope = value; }
        }

        private int _offset;
        /// <summary>
        /// Gets or sets the offset.
        /// </summary>
        /// <value>The offset.</value>
        public int Offset
        {
            get { return _offset; }
            set { _offset = value; }
        }

        private int _length;
        /// <summary>
        /// Gets or sets the length.
        /// </summary>
        /// <value>The length.</value>
        public int Length
        {
            get { return _length; }
            set { _length = value; }
        }

        private string _text;
        /// <summary>
        /// Gets or sets the value.
        /// </summary>
        /// <value>The value.</value>
        public string Text
        {
            get { return _text; }
            set { _text = value; }
        }

        private string _name;
        /// <summary>
        /// Gets or sets the display text.
        /// </summary>
        /// <value>The display text.</value>
        public string Name
        {
            get
            {
                if (string.IsNullOrEmpty(_name))
                    return Text;

                return _name;
            }
            set { _name = value; }
        }

        private Control _control;
        /// <summary>
        /// Gets the control.
        /// </summary>
        /// <value>The control.</value>
        public Control Control
        {
            get 
            {
                if (_control == null)
                {
                    if (IsScope)
                        _control = CreateScopeControl();
                    else
                        _control = CreateEmptyScopeControl();
                }

                return _control; 
            }
        }

        private int GetIndexInScopeList()
        {
            int index = Parent.Scopes.IndexOf(this);

            if (index == -1)
                throw (new ApplicationException("Scope not member of scope list."));

            return index;
        }

        internal TextScope GetPreviousScope()
        {
            int index = GetIndexInScopeList();

            if (index > 0)
                return Parent.Scopes[index-1];

            return null;
        }

        internal TextScope GetNextScope()
        {
            int index = GetIndexInScopeList();

            if (index < Parent.Scopes.Count - 1)
                return Parent.Scopes[index + 1];

            return null;
        }

        private Control CreateScopeControl()
        {
            ScopeControl scopeControl = new ScopeControl(this);
            scopeControl.RemoveScope += new EventHandler(RemoveScopeClick);

            return scopeControl;
        }

        void RemoveScopeClick(object sender, EventArgs e)
        {
            Parent.OnScopeRemoveClick(this, GetPreviousScope(), GetNextScope());
        }

        void CreateScopeClick(object sender, EventArgs e)
        {
            ToolStripMenuItem menuItem = (ToolStripMenuItem)sender;
            TextBox textBox = (TextBox)Control;

            if (string.IsNullOrEmpty(textBox.SelectedText))
                return;

            string beforeSelectionText = textBox.Text.Substring(0, textBox.SelectionStart);
            string selectedText = textBox.SelectedText;
            string afterSelectionText = textBox.Text.Substring(textBox.SelectionStart + textBox.SelectionLength);

            Parent.OnCreateScopeClick(this, menuItem, beforeSelectionText, selectedText, afterSelectionText);
        }

        private Control CreateEmptyScopeControl()
        {
            TextBox textBox = new TextBox();
#if !DEBUG
            textBox.BorderStyle = BorderStyle.None;
            textBox.Location = new Point(0, 3);
#endif
            textBox.ReadOnly = true;
            textBox.Text = Text;
            textBox.BackColor = Parent.BackColor;
            // textBox.Tag = ;

            ContextMenuStrip menu = new ContextMenuStrip();
            ToolStripMenuItem menuItem = new ToolStripMenuItem("&Create scope");
            menuItem.Click += new EventHandler(CreateScopeClick);
            // menuItem.Tag = scope;
            menu.Items.Add(menuItem);

            textBox.ContextMenuStrip = menu;

            textBox.SelectionStart = textBox.SelectionLength = 0;

            return textBox;
        }

        #region IComparable<TextScope> Members

        /// <summary>
        /// Compares the current object with another object of the same type.
        /// </summary>
        /// <param name="other">An object to compare with this object.</param>
        /// <returns>
        /// A 32-bit signed integer that indicates the relative order of the objects being compared. The return value has the following meanings:
        /// Value
        /// Meaning
        /// Less than zero
        /// This object is less than the <paramref name="other"/> parameter.
        /// Zero
        /// This object is equal to <paramref name="other"/>.
        /// Greater than zero
        /// This object is greater than <paramref name="other"/>.
        /// </returns>
        public int CompareTo(TextScope other)
        {
            return Offset - other.Offset;
        }

        #endregion
    }
}
